package model;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanFactoryException;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.DuplicateKeyException;
import org.mybeans.factory.MatchArg;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;

import com.mysql.jdbc.Connection;


import databeans.Fund;
import databeans.FundHistory;

/*
 * 
 * made by alesmana@andrew.cmu.edu
 * class for 15-600 homework 9
 * 
 * UserDAO
 * 
 */

public class FundHistoryDAO {
    private BeanFactory<FundHistory> factory;

    
    public FundHistoryDAO() throws DAOException {
        try {
            // Get a BeanTable so we can create the "employee" table
            BeanTable<FundHistory> fundHistoryTable = BeanTable.getInstance(FundHistory.class, "cfa_fundhistory");

            if (!fundHistoryTable.exists()) {
                fundHistoryTable.create("fundID" , "priceDate"); //FundID and pricedate  will be the PK for the table

                fundHistoryTable.setIdleConnectionCleanup(true); //see below explanation
                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = fundHistoryTable.getFactory();
                
                //initially populate with sample data
                bootData();
            } else {
                // Long running web apps need to clean up idle database connections.
                // So we can tell each BeanTable to clean them up. (You would only notice
                // a problem after leaving your web app running for several hours.)
                fundHistoryTable.setIdleConnectionCleanup(true);

                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = fundHistoryTable.getFactory();
            }

        } catch (BeanFactoryException e) {
            throw new DAOException(e);
        }
    }
   

    private void bootData() throws DAOException {
        
        FundHistory fh = new FundHistory();
        
        int totalDaysToDo = 365;
        Random randomGenerator = new Random();
        
        for (int a=0;a<totalDaysToDo;a++) {
        	for (int b=1;b<=4;b++) {
        		//note a single random object is reused here. +41 to bring it between 40-60
        		String randomTens = String.valueOf((randomGenerator.nextInt(20)+41));
        		String randomDP1 = String.valueOf((randomGenerator.nextInt(9)));
        		String randomDP2 = String.valueOf((randomGenerator.nextInt(9)));
        		String combined = randomTens + randomDP1 + randomDP2;
        		
        		Calendar cal = Calendar.getInstance();

                // Subtract days from the calendar
                cal.add(Calendar.DATE, -(totalDaysToDo-a));
        		
                fh.setFundID(b);
                fh.setPrice(Long.parseLong(combined));
                Date d = cal.getTime();
                fh.setPriceDate(d);
                create(fh);
            }	
        }
    }

    public void create(FundHistory fundHistory) throws DAOException {
        try {
            Transaction.begin();
            FundHistory dbFundHistory = factory.create(fundHistory.getFundID(), fundHistory.getPriceDate());
            
            //fundHistory.setFundID(dbFundHistory.getFundID());
            //fundHistory.setPriceDate(dbFundHistory.getPriceDate());
            factory.copyInto(fundHistory, dbFundHistory);
            Transaction.commit();
        } catch (DuplicateKeyException e) {
            throw new DAOException("A fund history record with ID " + fundHistory.getFundID() + " has already exists");
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    
    public void createByAlvin(FundHistory fundHistory) throws DAOException {
        try {
            Transaction.begin();
            FundHistory dbFundHistory = factory.create(fundHistory.getFundID(), fundHistory.getPriceDate());
            
            //fundHistory.setFundID(dbFundHistory.getFundID());
            //fundHistory.setPriceDate(dbFundHistory.getPriceDate());
            factory.copyInto(fundHistory, dbFundHistory);
            Transaction.commit();
        } catch (DuplicateKeyException e) {
            throw new DAOException("A fund history record with ID " + fundHistory.getFundID() + " has already exists");
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    
    /*
    public void delete(int id) throws DAOException {
        try {
            Transaction.begin();
            Fund f = factory.lookup(id);

            if (f == null) {
                throw new DAOException("Fund does not exist: id=" + id);
            }

            factory.delete(id);
            Transaction.commit();
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    */

    public FundHistory lookup(int fundID, Date date) throws DAOException {
        try {
            return factory.lookup(fundID, date);
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }

    protected BeanFactory<FundHistory> getFactory() {
        return factory;
    }

    public FundHistory[] getFundHistories() throws DAOException {
        try {
            FundHistory[] fundHistories = factory.match();
            Arrays.sort(fundHistories); // we want them to sort based on comparable compare
            return fundHistories;
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }
    
    //get Fund history based on fund ID
    public FundHistory[] getFundHistories(int fundID) throws DAOException {
        try {
            FundHistory[] fundHistories = factory.match(MatchArg.equals("fundID", fundID));
            Arrays.sort(fundHistories); // we want them to sort based on comparable compare
            return fundHistories;
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }

    public boolean checkDuplicates(FundHistory f) throws DAOException {
        boolean gotDuplicates = false;
        try {
            FundHistory[] list = factory.match(MatchArg.equals("fundID", f.getFundID()), MatchArg.equals("priceDate", f.getPriceDate()));
            if (list.length != 0) {
                gotDuplicates = true;
            }
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
        return gotDuplicates;
    }

    public void update(FundHistory fh) throws DAOException {
        try {
            Transaction.begin();
            int id = fh.getFundID();
            Date gc = fh.getPriceDate();
            FundHistory dbFundHistory = factory.lookup(id, gc);
        
            if (dbFundHistory == null) {
                throw new DAOException("Fund History does not exist fundid= " + id + " date=" + gc.toString());
            }
            
            dbFundHistory.setPrice(fh.getPrice());
            Transaction.commit();
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }

    

}
